﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;

using HeapModel;
using HeapModel.ProgInfo;
using HeapModel.RegionPartition;

using MetricExtractor;

namespace MetricProcessor
{
	class Program
	{
		private static string ROOT_DIR = null;
		private static string CSV_DUMP = null;

		static void Main(string[] args)
		{
			ROOT_DIR = @"C:\Users\a-markma\Documents\Visual Studio 2012\Projects\heapdbg\SampleData\luindex\bin\HeapDumps\"; //Directory.GetCurrentDirectory();
			CSV_DUMP = Path.Combine(ROOT_DIR, "metrics.csv");

			Console.WriteLine("Processing Files...");

			string[] filestoproc = Directory.GetFiles(ROOT_DIR, "*.xml");

			Dictionary<string, Tuple<bool, int>> singleregiontype = new Dictionary<string, Tuple<bool, int>>();
			List<RegionGraph> toproc = new List<RegionGraph>();

			MetricInfo minfo = new MetricInfo("prog1", singleregiontype);

			foreach(string fstr in filestoproc)
			{
				RegionGraph rg = ProcessSingleFileForSingletonAndSingleRegionTypes(fstr, singleregiontype);
				toproc.Add(rg);
			}

			for(int j = 0; j < toproc.Count; ++j)
				ProcessSingleHeapGraph(toproc[j], minfo, singleregiontype);

			StringBuilder sbrgnregioncentric = new StringBuilder("RegionInfoPerNodes\nProgram");
			for(int i = 0; i < IndivRegionMetrics.RegionInfoHeaders.Length; ++i)
				sbrgnregioncentric.Append(", " + IndivRegionMetrics.RegionInfoHeaders[i]);

			StringBuilder infoedge = new StringBuilder("SingleEdgeInfo\nProgram");
			for(int i = 0; i < IndivEdgeMetrics.IndiEdgeMetricsPerEdge.Length; ++i)
				infoedge.Append(", " + IndivEdgeMetrics.IndiEdgeMetricsPerEdge[i]);

			StringBuilder sbstructedge = new StringBuilder("StructureEdgeInfo\nProgram");
			for(int i = 0; i < BasicHeapStructureMetrics.StructMetricsPerEdge.Length; ++i)
				sbstructedge.Append(", " + BasicHeapStructureMetrics.StructMetricsPerEdge[i]);

			string inforgn = minfo.CSVFormatRgn();
			sbrgnregioncentric.Append("\n" + inforgn);

			string infoedges = minfo.CSVFormatEdges();
			infoedge.Append("\n" + infoedges);

			string infostruct = minfo.CSVFormatStructure();
			sbstructedge.Append("\n" + infostruct);

			System.IO.File.WriteAllText(CSV_DUMP, sbrgnregioncentric.ToString() + "\n\n" + infoedge.ToString() + "\n\n" + sbstructedge.ToString() + "\n\n");
		}

		private static RegionGraph ProcessSingleFileForSingletonAndSingleRegionTypes(string file, Dictionary<String, Tuple<bool, int>> singleregionandmaxsizemap)
		{
			RegionGraph hg = LoadSerializedHeap(file);
			SingletonAndSingleRgnTypeExtractor.Extract(hg, singleregionandmaxsizemap);

			return hg;
		}

		private static void ProcessSingleHeapGraph(RegionGraph hg, MetricInfo minfo, Dictionary<string, Tuple<bool, int>> singleregionandmaxsizemap)
		{ minfo.Extract(hg, singleregionandmaxsizemap); }

		private static RegionGraph LoadSerializedHeap(string file)
		{
			if(!File.Exists(file))
				throw new ArgumentException("File Not Found!!!");

			System.Xml.XmlReader rr = System.Xml.XmlReader.Create(new System.IO.StreamReader(file), new System.Xml.XmlReaderSettings() { IgnoreWhitespace = true });
			Dictionary<string, HeapModel.ProgInfo.TypeIdentifier> typedict = new Dictionary<string, HeapModel.ProgInfo.TypeIdentifier>();
			Dictionary<string, HeapModel.ProgInfo.OffsetIdentifier> offsetdict = new Dictionary<string, HeapModel.ProgInfo.OffsetIdentifier>();

			typedict.Add("null", new TypeIdentifier("null", TypeIdentifier.TypeCategory.Null));
			HeapModel.ConcreteMemory.ConcreteHeap ch = HeapModel.ConcreteMemory.ConcreteHeap.ReadConcreteMemory(rr, typedict, offsetdict);

			HeapModel.RegionPartition.RegionGraph rawheap = HeapModel.RegionPartition.RegionGraph.Create_NoNorm(ch, new HashSet<HeapModel.ProgInfo.TypeIdentifier>(typedict.Values));
			//rawheap.WriteDgml("./rawdump.dgml");

			HeapModel.RegionPartition.RegionGraph rg = HeapModel.RegionPartition.RegionGraph.Create(ch, new HashSet<HeapModel.ProgInfo.TypeIdentifier>(typedict.Values));
			//rg.WriteDgml("./rgdump.dgml");

			return rg;
		}
	}
}
